home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / os20 / wb / toolmanager2_0.lha / ToolManager / Source / prefs / dockwindow.c < prev    next >
C/C++ Source or Header  |  1992-09-26  |  34KB  |  1,099 lines

  1. /*
  2.  * dockwindow.c  V2.0
  3.  *
  4.  * dock edit window handling
  5.  *
  6.  * (c) 1990-1992 Stefan Becker
  7.  */
  8.  
  9. #include "ToolManagerConf.h"
  10.  
  11. struct DockNode {
  12.                  struct Node      dn_Node;
  13.                  ULONG            dn_Flags;
  14.                  char            *dn_HotKey;
  15.                  char            *dn_PubScreen;
  16.                  char            *dn_Title;
  17.                  struct TextAttr  dn_Font;
  18.                  char            *dn_FontDesc;
  19.                  LONG             dn_XPos;
  20.                  LONG             dn_YPos;
  21.                  ULONG            dn_Columns;
  22.                  struct List     *dn_ToolsList;
  23.                 };
  24.  
  25. /* Window data */
  26. static struct Gadget *gl;             /* Gadget list */
  27. static struct Window *w;              /* Window */
  28. static struct MsgPort *wp;            /* Window user port */
  29. static UWORD ww,wh;                   /* Window size */
  30. static struct DockNode *CurrentNode;
  31. static struct Gadget *CurrentGadget;
  32. static ULONG CurrentGadgetNum;
  33. static BOOL ReqOpen;
  34. #define WINDOW_IDCMP (IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW|BUTTONIDCMP|\
  35.                       CHECKBOXIDCMP|STRINGIDCMP)
  36.  
  37. /* Gadget data */
  38. #define GAD_NAME_STR     0 /* Gadgets with labels (left side) */
  39. #define GAD_TITLE_STR    1
  40. #define GAD_HOTKEY_STR   2
  41. #define GAD_XPOS_INT     3
  42. #define GAD_YPOS_INT     4
  43. #define GAD_COLUMNS_INT  5
  44.  
  45. #define GAD_POSITION     6 /* Cycle gadget */
  46.  
  47. #define GAD_PSCREEN_BUT  7 /* Gadgets with labels (right side) */
  48. #define GAD_FONT_BUT     8
  49.  
  50. #define GAD_PSCREEN_STR  9
  51. #define GAD_FONT_TXT    10
  52.  
  53. #define GAD_TOOLS       11 /* Button gadget */
  54.  
  55. #define GAD_ACTIVATED   12 /* Checkbox gadgets */
  56. #define GAD_CENTERED    13
  57. #define GAD_FRONTMOST   14
  58. #define GAD_MENU        15
  59. #define GAD_PATTERN     16
  60. #define GAD_POPUP       17
  61. #define GAD_TEXT        18
  62. #define GAD_VERTICAL    19
  63.  
  64. #define GAD_OK          20 /* Button gadgets */
  65. #define GAD_CANCEL      21
  66. #define GADGETS         22
  67. static struct GadgetData gdata[GADGETS];
  68.  
  69. /* Gadget tags */
  70. static struct TagItem nametags[]={GTST_String,   NULL,
  71.                                   GTST_MaxChars, 100,
  72.                                   TAG_DONE};
  73.  
  74. static struct TagItem hotktags[]={GTST_String,   NULL,
  75.                                   GTST_MaxChars, 100,
  76.                                   TAG_DONE};
  77.  
  78. static struct TagItem pbsctags[]={GTST_String,   NULL,
  79.                                   GTST_MaxChars, 100,
  80.                                   TAG_DONE};
  81.  
  82. static struct TagItem fonttags[]={GTTX_Text,   NULL,
  83.                                   GTTX_Border, TRUE,
  84.                                   TAG_DONE};
  85.  
  86. static struct TagItem titletags[]={GTST_String,   NULL,
  87.                                    GTST_MaxChars, 100,
  88.                                    TAG_DONE};
  89.  
  90. static struct TagItem xpostags[]={GTIN_Number,   0,
  91.                                   GTIN_MaxChars, 10,
  92.                                   TAG_DONE};
  93.  
  94. static struct TagItem ypostags[]={GTIN_Number,   0,
  95.                                   GTIN_MaxChars, 10,
  96.                                   TAG_DONE};
  97.  
  98. static char *cyclelabels[3]={NULL, NULL, NULL};
  99. static struct TagItem cycletags[]={GTCY_Labels, cyclelabels,
  100.                                    GTCY_Active, 0,
  101.                                    TAG_DONE};
  102.  
  103. static struct TagItem colstags[]={GTIN_Number,   0,
  104.                                   GTIN_MaxChars, 10,
  105.                                   TAG_DONE};
  106.  
  107. static struct TagItem actitags[]={GTCB_Checked, FALSE,
  108.                                   TAG_DONE};
  109.  
  110. static struct TagItem centtags[]={GTCB_Checked, FALSE,
  111.                                   TAG_DONE};
  112.  
  113. static struct TagItem fronttags[]={GTCB_Checked, FALSE,
  114.                                    TAG_DONE};
  115.  
  116. static struct TagItem menutags[]={GTCB_Checked, FALSE,
  117.                                   TAG_DONE};
  118.  
  119. static struct TagItem patttags[]={GTCB_Checked, FALSE,
  120.                                   TAG_DONE};
  121.  
  122. static struct TagItem popuptags[]={GTCB_Checked, FALSE,
  123.                                    TAG_DONE};
  124.  
  125. static struct TagItem texttags[]={GTCB_Checked, FALSE,
  126.                                   TAG_DONE};
  127.  
  128. static struct TagItem verttags[]={GTCB_Checked, FALSE,
  129.                                   TAG_DONE};
  130.  
  131. /* Init dock edit window */
  132. void InitDockEditWindow(UWORD left, UWORD fheight)
  133. {
  134.  ULONG llabwidth,lgadwidth,rlabwidth,rgadwidth;
  135.  ULONG cycwidth,cbwidth,butwidth,minstringwidth;
  136.  ULONG strheight=fheight+2;
  137.  ULONG i,tmp,yadd;
  138.  struct GadgetData *gd;
  139.  
  140.  /* Init strings */
  141.  gdata[GAD_NAME_STR].name    =AppStrings[MSG_WINDOW_NAME_GAD];
  142.  gdata[GAD_TITLE_STR].name   =AppStrings[MSG_DOCKWIN_TITLE_GAD];
  143.  gdata[GAD_HOTKEY_STR].name  =AppStrings[MSG_WINDOW_HOTKEY_GAD];
  144.  gdata[GAD_XPOS_INT].name    =AppStrings[MSG_WINDOW_LEFTEDGE_GAD];
  145.  gdata[GAD_YPOS_INT].name    =AppStrings[MSG_WINDOW_TOPEDGE_GAD];
  146.  gdata[GAD_COLUMNS_INT].name =AppStrings[MSG_DOCKWIN_COLUMNS_GAD];
  147.  cyclelabels[0]              =AppStrings[MSG_WINDOW_POSITION_OPEN_LABEL];
  148.  cyclelabels[1]              =AppStrings[MSG_WINDOW_POSITION_CLOSE_LABEL];
  149.  gdata[GAD_PSCREEN_BUT].name =AppStrings[MSG_WINDOW_PUBSCREEN_GAD];
  150.  gdata[GAD_FONT_BUT].name    =AppStrings[MSG_DOCKWIN_FONT_GAD];
  151.  gdata[GAD_TOOLS].name       =AppStrings[MSG_DOCKWIN_EDITTOOLS_GAD];
  152.  gdata[GAD_ACTIVATED].name   =AppStrings[MSG_DOCKWIN_ACTIVATED_GAD];
  153.  gdata[GAD_CENTERED].name    =AppStrings[MSG_DOCKWIN_CENTERED_GAD];
  154.  gdata[GAD_FRONTMOST].name   =AppStrings[MSG_DOCKWIN_FRONTMOST_GAD];
  155.  gdata[GAD_MENU].name        =AppStrings[MSG_DOCKWIN_MENU_GAD];
  156.  gdata[GAD_PATTERN].name     =AppStrings[MSG_DOCKWIN_PATTERN_GAD];
  157.  gdata[GAD_POPUP].name       =AppStrings[MSG_DOCKWIN_POPUP_GAD];
  158.  gdata[GAD_TEXT].name        =AppStrings[MSG_DOCKWIN_TEXT_GAD];
  159.  gdata[GAD_VERTICAL].name    =AppStrings[MSG_DOCKWIN_VERTICAL_GAD];
  160.  gdata[GAD_OK].name          =AppStrings[MSG_WINDOW_OK_GAD];
  161.  gdata[GAD_CANCEL].name      =AppStrings[MSG_WINDOW_CANCEL_GAD];
  162.  
  163.  /* Calculate maximum label width (left side) */
  164.  llabwidth=0;
  165.  gd=&gdata[GAD_NAME_STR];
  166.  for (i=GAD_NAME_STR; i<=GAD_COLUMNS_INT; i++, gd++)
  167.   if ((tmp=TextLength(&TmpRastPort,gd->name,strlen(gd->name))) > llabwidth)
  168.    llabwidth=tmp;
  169.  llabwidth+=INTERWIDTH;
  170.  
  171.  /* Calculate maximum gadget width (left side) */
  172.  minstringwidth=TextLength(&TmpRastPort,AppStrings[MSG_DOCKWIN_NEWNAME],
  173.                            strlen(AppStrings[MSG_DOCKWIN_NEWNAME]))
  174.                 +2*INTERWIDTH;
  175.  lgadwidth=minstringwidth;
  176.  
  177.  /* Calculate maximum cyclegadget width */
  178.  {
  179.   char **s;
  180.  
  181.   cycwidth=0;
  182.   s=cyclelabels;
  183.   for (i=0; i<=1; i++, s++)
  184.    if ((tmp=TextLength(&TmpRastPort,*s,strlen(*s))) > cycwidth)
  185.     cycwidth=tmp;
  186.   cycwidth+=5*INTERWIDTH;
  187.  }
  188.  if ((llabwidth+lgadwidth+INTERWIDTH) < cycwidth)
  189.   lgadwidth=cycwidth-llabwidth-INTERWIDTH;
  190.  
  191.  /* Calculate maximum label width (right side) */
  192.  gd=&gdata[GAD_PSCREEN_BUT];
  193.  rlabwidth=TextLength(&TmpRastPort,gd->name,strlen(gd->name))+INTERWIDTH;
  194.  gd++;
  195.  if ((tmp=TextLength(&TmpRastPort,gd->name,strlen(gd->name))+2*INTERWIDTH)
  196.       > rlabwidth)
  197.   rlabwidth=tmp;
  198.  
  199.  /* Calculate maximum gadget width (right side) */
  200.  rgadwidth=minstringwidth+REQBUTTONWIDTH;
  201.  
  202.  /* Calculate maximum button gadget width */
  203.  gd=&gdata[GAD_TOOLS];
  204.  butwidth=TextLength(&TmpRastPort,gd->name,strlen(gd->name))+2*INTERWIDTH;
  205.  if ((rlabwidth+rgadwidth+INTERWIDTH) < butwidth)
  206.   rgadwidth=butwidth-rlabwidth-INTERWIDTH;
  207.  
  208.  /* Calculate maximum checkbox gadget width */
  209.  cbwidth=0;
  210.  gd=&gdata[GAD_ACTIVATED];
  211.  for (i=GAD_ACTIVATED; i<=GAD_VERTICAL; i++, gd++)
  212.   if ((tmp=TextLength(&TmpRastPort,gd->name,strlen(gd->name))) > cbwidth)
  213.    cbwidth=tmp;
  214.  cbwidth+=CHKBOXWIDTH+INTERWIDTH;
  215.  if ((rlabwidth+rgadwidth) < 2*cbwidth)
  216.   rgadwidth=2*cbwidth-rlabwidth;
  217.  
  218.  /* Calculate minimum window width */
  219.  ww=llabwidth+lgadwidth+rlabwidth+rgadwidth+4*INTERWIDTH;
  220.  
  221.  /* Calculate button gadgets width */
  222.  gd=&gdata[GAD_OK];
  223.  butwidth=TextLength(&TmpRastPort,gd->name,strlen(gd->name));
  224.  gd++;
  225.  if ((tmp=TextLength(&TmpRastPort,gd->name,strlen(gd->name))) > butwidth)
  226.   butwidth=tmp;
  227.  butwidth+=2*INTERWIDTH;
  228.  if ((tmp=2*(butwidth+INTERWIDTH)) > ww) ww=tmp;
  229.  
  230.  /* Calculate minimum window height */
  231.  wh=8*fheight+9*INTERHEIGHT+14;
  232.  
  233.  /* Init gadgets */
  234.  gd=gdata;
  235.  tmp=(ww-llabwidth-lgadwidth-rlabwidth-rgadwidth-4*INTERWIDTH)/2;
  236.  lgadwidth+=tmp; /* String gadget length (left) */
  237.  rgadwidth+=tmp; /* String gadget length (right) */
  238.  llabwidth+=left+INTERWIDTH;
  239.  tmp=WindowTop+INTERHEIGHT;
  240.  yadd=strheight+INTERHEIGHT;
  241.  
  242.  /* Name string gadget */
  243.  gd->type=STRING_KIND;
  244.  gd->flags=PLACETEXT_LEFT;
  245.  gd->tags=nametags;
  246.  gd->left=llabwidth;
  247.  gd->top=tmp;
  248.  gd->width=lgadwidth;
  249.  gd->height=strheight;
  250.  tmp+=yadd;
  251.  
  252.  /* Title string gadget */
  253.  gd++;
  254.  gd->type=STRING_KIND;
  255.  gd->flags=PLACETEXT_LEFT;
  256.  gd->tags=titletags;
  257.  gd->left=llabwidth;
  258.  gd->top=tmp;
  259.  gd->width=lgadwidth;
  260.  gd->height=strheight;
  261.  tmp+=yadd;
  262.  
  263.  /* HotKey string gadget */
  264.  gd++;
  265.  gd->type=STRING_KIND;
  266.  gd->flags=PLACETEXT_LEFT;
  267.  gd->tags=hotktags;
  268.  gd->left=llabwidth;
  269.  gd->top=tmp;
  270.  gd->width=lgadwidth;
  271.  gd->height=strheight;
  272.  tmp+=2*yadd;
  273.  
  274.  /* LeftEdge integer gadget */
  275.  gd++;
  276.  gd->type=INTEGER_KIND;
  277.  gd->flags=PLACETEXT_LEFT;
  278.  gd->tags=xpostags;
  279.  gd->left=llabwidth;
  280.  gd->top=tmp;
  281.  gd->width=lgadwidth;
  282.  gd->height=strheight;
  283.  tmp+=yadd;
  284.  
  285.  /* TopEdge integer gadget */
  286.  gd++;
  287.  gd->type=INTEGER_KIND;
  288.  gd->flags=PLACETEXT_LEFT;
  289.  gd->tags=ypostags;
  290.  gd->left=llabwidth;
  291.  gd->top=tmp;
  292.  gd->width=lgadwidth;
  293.  gd->height=strheight;
  294.  tmp+=yadd;
  295.  
  296.  /* Columns integer gadget */
  297.  gd++;
  298.  gd->type=INTEGER_KIND;
  299.  gd->flags=PLACETEXT_LEFT;
  300.  gd->tags=colstags;
  301.  gd->left=llabwidth;
  302.  gd->top=tmp;
  303.  gd->width=lgadwidth;
  304.  gd->height=strheight;
  305.  
  306.  /* Position cycle gadget */
  307.  tmp=WindowTop+3*yadd+INTERHEIGHT;
  308.  gd++;
  309.  gd->type=CYCLE_KIND;
  310.  gd->flags=PLACETEXT_IN;
  311.  gd->tags=cycletags;
  312.  gd->left=left;
  313.  gd->top=tmp;
  314.  gd->width=lgadwidth+llabwidth-left;
  315.  gd->height=strheight;
  316.  
  317.  /* PubScreen button gadget */
  318.  tmp=WindowTop+INTERHEIGHT;
  319.  llabwidth=ww-rgadwidth-INTERWIDTH+left;
  320.  gd++;
  321.  gd->type=GENERIC_KIND;
  322.  gd->flags=0;
  323.  gd->left=llabwidth;
  324.  gd->top=tmp;
  325.  gd->width=REQBUTTONWIDTH;
  326.  gd->height=strheight;
  327.  tmp+=yadd;
  328.  
  329.  /* Font button gadget */
  330.  gd++;
  331.  gd->type=BUTTON_KIND;
  332.  gd->flags=PLACETEXT_IN;
  333.  gd->left=llabwidth-rlabwidth-INTERWIDTH;
  334.  gd->top=tmp;
  335.  gd->width=rlabwidth;
  336.  gd->height=strheight;
  337.  
  338.  /* PubScreen string gadget */
  339.  tmp=WindowTop+INTERHEIGHT;
  340.  gd++;
  341.  gd->type=STRING_KIND;
  342.  gd->tags=pbsctags;
  343.  gd->left=llabwidth+REQBUTTONWIDTH;
  344.  gd->top=tmp;
  345.  gd->width=rgadwidth-REQBUTTONWIDTH;
  346.  gd->height=strheight;
  347.  tmp+=yadd;
  348.  
  349.  /* Font text gadget */
  350.  gd++;
  351.  gd->type=TEXT_KIND;
  352.  gd->tags=fonttags;
  353.  gd->left=llabwidth;
  354.  gd->top=tmp;
  355.  gd->width=rgadwidth;
  356.  gd->height=strheight;
  357.  tmp+=yadd;
  358.  
  359.  /* Tools button gadget */
  360.  llabwidth-=rlabwidth+INTERWIDTH;
  361.  gd++;
  362.  gd->type=BUTTON_KIND;
  363.  gd->flags=PLACETEXT_IN;
  364.  gd->left=llabwidth;
  365.  gd->top=tmp;
  366.  gd->width=ww-llabwidth-INTERWIDTH+left;
  367.  gd->height=strheight;
  368.  tmp+=yadd+1;
  369.  
  370.  /* Activated checkbox gadget */
  371.  rlabwidth=(ww-llabwidth-INTERWIDTH+left-2*cbwidth)/3;
  372.  llabwidth+=rlabwidth;
  373.  cbwidth+=llabwidth+rlabwidth;
  374.  
  375.  gd++;
  376.  gd->type=CHECKBOX_KIND;
  377.  gd->flags=PLACETEXT_RIGHT;
  378.  gd->tags=actitags;
  379.  gd->left=llabwidth;
  380.  gd->top=tmp;
  381.  gd->width=CHKBOXWIDTH;
  382.  gd->height=strheight;
  383.  
  384.  /* Centered checkbox gadget */
  385.  gd++;
  386.  gd->type=CHECKBOX_KIND;
  387.  gd->flags=PLACETEXT_RIGHT;
  388.  gd->tags=centtags;
  389.  gd->left=cbwidth;
  390.  gd->top=tmp;
  391.  gd->width=CHKBOXWIDTH;
  392.  gd->height=strheight;
  393.  tmp+=yadd;
  394.  
  395.  /* Frontmost checkbox gadget */
  396.  gd++;
  397.  gd->type=CHECKBOX_KIND;
  398.  gd->flags=PLACETEXT_RIGHT;
  399.  gd->tags=fronttags;
  400.  gd->left=llabwidth;
  401.  gd->top=tmp;
  402.  gd->width=CHKBOXWIDTH;
  403.  gd->height=strheight;
  404.  
  405.  /* Menu checkbox gadget */
  406.  gd++;
  407.  gd->type=CHECKBOX_KIND;
  408.  gd->flags=PLACETEXT_RIGHT;
  409.  gd->tags=menutags;
  410.  gd->left=cbwidth;
  411.  gd->top=tmp;
  412.  gd->width=CHKBOXWIDTH;
  413.  gd->height=strheight;
  414.  tmp+=yadd;
  415.  
  416.  /* Pattern checkbox gadget */
  417.  gd++;
  418.  gd->type=CHECKBOX_KIND;
  419.  gd->flags=PLACETEXT_RIGHT;
  420.  gd->tags=patttags;
  421.  gd->left=llabwidth;
  422.  gd->top=tmp;
  423.  gd->width=CHKBOXWIDTH;
  424.  gd->height=strheight;
  425.  
  426.  /* PopUp checkbox gadget */
  427.  gd++;
  428.  gd->type=CHECKBOX_KIND;
  429.  gd->flags=PLACETEXT_RIGHT;
  430.  gd->tags=popuptags;
  431.  gd->left=cbwidth;
  432.  gd->top=tmp;
  433.  gd->width=CHKBOXWIDTH;
  434.  gd->height=strheight;
  435.  tmp+=yadd;
  436.  
  437.  /* Text checkbox gadget */
  438.  gd++;
  439.  gd->type=CHECKBOX_KIND;
  440.  gd->flags=PLACETEXT_RIGHT;
  441.  gd->tags=texttags;
  442.  gd->left=llabwidth;
  443.  gd->top=tmp;
  444.  gd->width=CHKBOXWIDTH;
  445.  gd->height=strheight;
  446.  
  447.  /* Vertical checkbox gadget */
  448.  gd++;
  449.  gd->type=CHECKBOX_KIND;
  450.  gd->flags=PLACETEXT_RIGHT;
  451.  gd->tags=verttags;
  452.  gd->left=cbwidth;
  453.  gd->top=tmp;
  454.  gd->width=CHKBOXWIDTH;
  455.  gd->height=strheight;
  456.  tmp+=yadd-1;
  457.  
  458.  /* OK button gadget */
  459.  gd++;
  460.  gd->type=BUTTON_KIND;
  461.  gd->flags=PLACETEXT_IN;
  462.  gd->left=left;
  463.  gd->top=tmp;
  464.  gd->width=butwidth;
  465.  gd->height=fheight;
  466.  
  467.  /* Cancel button gadget */
  468.  gd++;
  469.  gd->type=BUTTON_KIND;
  470.  gd->flags=PLACETEXT_IN;
  471.  gd->left=ww-butwidth-INTERWIDTH+left;
  472.  gd->top=tmp;
  473.  gd->width=butwidth;
  474.  gd->height=fheight;
  475. }
  476.  
  477. /* Free dock node */
  478. void FreeDockNode(struct Node *node)
  479. {
  480.  struct DockNode *dn=node;
  481.  char *s;
  482.  
  483.  if (s=dn->dn_Node.ln_Name) free(s);
  484.  if (s=dn->dn_HotKey) free(s);
  485.  if (s=dn->dn_PubScreen) free(s);
  486.  if (s=dn->dn_Title) free(s);
  487.  if (s=dn->dn_Font.ta_Name) free(s);
  488.  if (s=dn->dn_FontDesc) free(s);
  489.  
  490.  /* Free tool list */
  491.  if (dn->dn_ToolsList) FreeToolsList(dn->dn_ToolsList);
  492.  
  493.  /* Free node */
  494.  FreeMem(dn,sizeof(struct DockNode));
  495. }
  496.  
  497. /* Build font descriptor string */
  498. static char *BuildFontDesc(struct TextAttr *ta)
  499. {
  500.  char *name;
  501.  
  502.  if (name=strdup(ta->ta_Name)) {
  503.   ULONG len=strlen(name);
  504.   UWORD size=ta->ta_YSize%10000; /* Safety hack... */
  505.   UWORD div=1000;
  506.   char *s=&name[len-5];
  507.   BOOL InNumber=FALSE;
  508.  
  509.   /* Overwrite ".font" */
  510.   *s++='/';
  511.   while (div) {
  512.    char c=size/div+'0';
  513.  
  514.    if ((c!='0') || InNumber) {
  515.     *s++=c;
  516.     InNumber=TRUE;
  517.    }
  518.    size%=div;
  519.    div/=10;
  520.   }
  521.   *s++='\0';
  522.  }
  523.  return(name);
  524. }
  525.  
  526. /* Copy dock node */
  527. struct Node *CopyDockNode(struct Node *node)
  528. {
  529.  struct DockNode *dn,*orignode=node;
  530.  
  531.  /* Alloc memory for exec node */
  532.  if (dn=AllocMem(sizeof(struct DockNode),MEMF_PUBLIC|MEMF_CLEAR)) {
  533.   /* Got an old node? */
  534.   if (orignode) {
  535.    /* Yes, copy it */
  536.    if ((!orignode->dn_Node.ln_Name || (dn->dn_Node.ln_Name=
  537.                                         strdup(orignode->dn_Node.ln_Name))) &&
  538.        (!orignode->dn_HotKey || (dn->dn_HotKey=strdup(orignode->dn_HotKey))) &&
  539.        (!orignode->dn_PubScreen || (dn->dn_PubScreen=
  540.                                      strdup(orignode->dn_PubScreen))) &&
  541.        (!orignode->dn_Title || (dn->dn_Title=strdup(orignode->dn_Title))) &&
  542.        (!orignode->dn_Font.ta_Name ||
  543.         ((dn->dn_Font.ta_Name=strdup(orignode->dn_Font.ta_Name)) &&
  544.          (dn->dn_FontDesc=BuildFontDesc(&orignode->dn_Font)))) &&
  545.        (!orignode->dn_ToolsList || (dn->dn_ToolsList=
  546.                                      CopyToolsList(orignode->dn_ToolsList)))) {
  547.     /* Copy flags & numbers */
  548.     dn->dn_XPos=orignode->dn_XPos;
  549.     dn->dn_YPos=orignode->dn_YPos;
  550.     dn->dn_Columns=orignode->dn_Columns;
  551.     dn->dn_Font.ta_YSize=orignode->dn_Font.ta_YSize;
  552.     dn->dn_Font.ta_Style=orignode->dn_Font.ta_Style;
  553.     dn->dn_Font.ta_Flags=orignode->dn_Font.ta_Flags;
  554.     dn->dn_Flags=orignode->dn_Flags;
  555.  
  556.     /* Return pointer to new node */
  557.     return(dn);
  558.    }
  559.   } else {
  560.    /* No, set defaults */
  561.    if (dn->dn_Node.ln_Name=strdup(AppStrings[MSG_DOCKWIN_NEWNAME])) {
  562.     dn->dn_Columns=1;
  563.     dn->dn_Flags=DOPOF_ACTIVATED;
  564.  
  565.     /* Return pointer to new node */
  566.     return(dn);
  567.    }
  568.   }
  569.  
  570.   FreeDockNode((struct Node *) dn);
  571.  }
  572.  /* Call failed */
  573.  return(NULL);
  574. }
  575.  
  576. /* Activate gadget and save pointer to it */
  577. static ActivateAndSetGadget(ULONG num)
  578. {
  579.  CurrentGadget=gdata[num].gadget;
  580.  ActivateGadget(CurrentGadget,w,NULL);
  581. }
  582.  
  583. /* Open dock edit window */
  584. BOOL OpenDockEditWindow(struct Node *node, struct Window *parent)
  585. {
  586.  /* Copy node */
  587.  if (CurrentNode=CopyDockNode(node)) {
  588.   /* Set tags */
  589.   nametags[0].ti_Data=CurrentNode->dn_Node.ln_Name;
  590.   titletags[0].ti_Data=CurrentNode->dn_Title;
  591.   hotktags[0].ti_Data=CurrentNode->dn_HotKey;
  592.   xpostags[0].ti_Data=CurrentNode->dn_XPos;
  593.   ypostags[0].ti_Data=CurrentNode->dn_YPos;
  594.   colstags[0].ti_Data=CurrentNode->dn_Columns;
  595.   pbsctags[0].ti_Data=CurrentNode->dn_PubScreen;
  596.   fonttags[0].ti_Data=CurrentNode->dn_FontDesc;
  597.   actitags[0].ti_Data=(CurrentNode->dn_Flags & DOPOF_ACTIVATED)!=0;
  598.   centtags[0].ti_Data=(CurrentNode->dn_Flags & DOPOF_CENTERED)!=0;
  599.   fronttags[0].ti_Data=(CurrentNode->dn_Flags & DOPOF_FRONTMOST)!=0;
  600.   menutags[0].ti_Data=(CurrentNode->dn_Flags & DOPOF_MENU)!=0;
  601.   patttags[0].ti_Data=(CurrentNode->dn_Flags & DOPOF_PATTERN)!=0;
  602.   popuptags[0].ti_Data=(CurrentNode->dn_Flags & DOPOF_POPUP)!=0;
  603.   texttags[0].ti_Data=(CurrentNode->dn_Flags & DOPOF_TEXT)!=0;
  604.   verttags[0].ti_Data=(CurrentNode->dn_Flags & DOPOF_VERTICAL)!=0;
  605.  
  606.   /* Create gadgets */
  607.   if (gl=CreateGadgetList(gdata,GADGETS)) {
  608.    /* Open window */
  609.    if (w=OpenWindowTags(NULL,WA_Left,parent->LeftEdge,
  610.                              WA_Top,parent->TopEdge+WindowTop,
  611.                              WA_InnerWidth,ww,
  612.                              WA_InnerHeight,wh,
  613.                              WA_AutoAdjust,TRUE,
  614.                              WA_Title,AppStrings[MSG_DOCKWIN_TITLE],
  615.                              WA_PubScreen,PublicScreen,
  616.                              WA_Flags,WFLG_CLOSEGADGET|WFLG_DRAGBAR|
  617.                                       WFLG_DEPTHGADGET|WFLG_RMBTRAP|
  618.                                       WFLG_ACTIVATE,
  619.                              TAG_DONE)) {
  620.     /* Init requester button gadgets */
  621.     InitReqButtonGadget(gdata[GAD_PSCREEN_BUT].gadget);
  622.  
  623.     /* Add gadgets to window */
  624.     AddGList(w,gl,(UWORD) -1,(UWORD) -1,NULL);
  625.     RefreshGList(gl,w,NULL,(UWORD) -1);
  626.     GT_RefreshWindow(w,NULL);
  627.  
  628.     /* Activate name string gadget */
  629.     ActivateAndSetGadget(GAD_NAME_STR);
  630.  
  631.     /* Set local variables */
  632.     w->UserPort=IDCMPPort;
  633.     w->UserData=HandleDockEditWindowIDCMP;
  634.     ModifyIDCMP(w,WINDOW_IDCMP);
  635.     CurrentWindow=w;
  636.     ReqOpen=FALSE;
  637.  
  638.     /* All OK. */
  639.     return(TRUE);
  640.    }
  641.    FreeGadgets(gl);
  642.   }
  643.   FreeDockNode((struct Node *) CurrentNode);
  644.  }
  645.  /* Call failed */
  646.  return(FALSE);
  647. }
  648.  
  649. /* Close dock edit window */
  650. static void CloseDockEditWindow(void)
  651. {
  652.  /* Free resources */
  653.  if (MoveWindowPtr) CloseMoveWindow();
  654.  RemoveGList(w,gl,(UWORD) -1);
  655.  CloseWindowSafely(w);
  656.  FreeGadgets(gl);
  657. }
  658.  
  659. /* If move window open, move it to new position */
  660. static void MoveMoveWindow(void)
  661. {
  662.  /* Move window open? */
  663.  if (MoveWindowPtr) {
  664.   ULONG x,y;
  665.  
  666.   /* Read current position */
  667.   x=((struct StringInfo *) gdata[GAD_XPOS_INT].gadget->SpecialInfo)->LongInt;
  668.   y=((struct StringInfo *) gdata[GAD_YPOS_INT].gadget->SpecialInfo)->LongInt;
  669.  
  670.   /* Move move window */
  671.   MoveWindow(MoveWindowPtr,x-MoveWindowPtr->LeftEdge,y-MoveWindowPtr->TopEdge);
  672.  }
  673. }
  674.  
  675. /* Handle dock edit window IDCMP events */
  676. void *HandleDockEditWindowIDCMP(struct IntuiMessage *msg)
  677. {
  678.  struct Node *NewNode=NULL;
  679.  
  680.  /* Which IDCMP class? */
  681.  switch (msg->Class) {
  682.   case IDCMP_CLOSEWINDOW:   NewNode=(struct Node *) -1;
  683.                             FreeDockNode((struct Node *) CurrentNode);
  684.                             break;
  685.   case IDCMP_REFRESHWINDOW: GT_BeginRefresh(w);
  686.                             GT_EndRefresh(w,TRUE);
  687.                             break;
  688.   case IDCMP_GADGETUP:
  689.    switch (((struct Gadget *) msg->IAddress)->GadgetID) {
  690.     case GAD_NAME_STR:    ActivateAndSetGadget(GAD_TITLE_STR);
  691.                           break;
  692.     case GAD_TITLE_STR:   ActivateAndSetGadget(GAD_HOTKEY_STR);
  693.                           break;
  694.     case GAD_HOTKEY_STR:  ActivateAndSetGadget(GAD_XPOS_INT);
  695.                           break;
  696.     case GAD_XPOS_INT:    MoveMoveWindow();
  697.                           ActivateAndSetGadget(GAD_YPOS_INT);
  698.                           break;
  699.     case GAD_YPOS_INT:    MoveMoveWindow();
  700.                           ActivateAndSetGadget(GAD_COLUMNS_INT);
  701.                           break;
  702.     case GAD_COLUMNS_INT: ActivateAndSetGadget(GAD_PSCREEN_STR);
  703.                           break;
  704.     case GAD_POSITION:    /* Move window open? */
  705.                           if (MoveWindowPtr)
  706.                            /* Yes, close move window */
  707.                            CloseMoveWindow();
  708.                           else {
  709.                            /* No. Open it! */
  710.                            MoveWindowOffX=0;
  711.                            MoveWindowOffY=0;
  712.  
  713.                            /* Open move window */
  714.                            OpenMoveWindow(w,gdata[GAD_XPOS_INT].gadget,
  715.                                             gdata[GAD_YPOS_INT].gadget);
  716.                           }
  717.  
  718.                           /* Activate old string gadget */
  719.                           ActivateGadget(CurrentGadget,w,NULL);
  720.                           break;
  721.     case GAD_PSCREEN_BUT: if (!ReqOpen) {
  722.                            /* Save current gadget number */
  723.                            CurrentGadgetNum=GAD_PSCREEN_BUT;
  724.  
  725.                            /* Open list requester */
  726.                            if (OpenListRequester(LISTREQ_PUBSC,w)) {
  727.                             /* Disable window */
  728.                             DisableWindow(w);
  729.  
  730.                             /* Set update function */
  731.                             UpdateWindow=UpdateDockEditWindow;
  732.                             ReqOpen=TRUE;
  733.                            } else
  734.                             ActivateGadget(CurrentGadget,w,NULL);
  735.                           }
  736.                           break;
  737.     case GAD_FONT_BUT:    {
  738.                            struct TextAttr *newta;
  739.  
  740.                            /* Set old font */
  741.                            newta=(CurrentNode->dn_FontDesc) ?
  742.                                   &CurrentNode->dn_Font : NULL;
  743.  
  744.                            /* Open font requester */
  745.                            if (newta=OpenFontRequester(w,newta)) {
  746.  
  747.                             /* Font specified? */
  748.                             if (newta->ta_Name) {
  749.                              char *fontdesc;
  750.  
  751.                              /* Build font descriptor */
  752.                              if (fontdesc=BuildFontDesc(newta)) {
  753.                               /* All OK. Set new font */
  754.                               GT_SetGadgetAttrs(gdata[GAD_FONT_TXT].gadget,w,
  755.                                                 NULL,GTTX_Text,fontdesc,
  756.                                                      TAG_DONE);
  757.  
  758.                               /* Throw away old font */
  759.                               if (CurrentNode->dn_FontDesc) {
  760.                                free(CurrentNode->dn_Font.ta_Name);
  761.                                free(CurrentNode->dn_FontDesc);
  762.                               }
  763.  
  764.                               /* Set new font */
  765.                               CurrentNode->dn_Font=*(newta);
  766.                               CurrentNode->dn_FontDesc=fontdesc;
  767.                              }
  768.                             } else
  769.                              /* User selected NO font, delete old one */
  770.                              if (CurrentNode->dn_FontDesc) {
  771.                               GT_SetGadgetAttrs(gdata[GAD_FONT_TXT].gadget,w,
  772.                                                 NULL,GTTX_Text,NULL,
  773.                                                      TAG_DONE);
  774.                               /* Free strings */
  775.                               free(CurrentNode->dn_Font.ta_Name);
  776.                               CurrentNode->dn_Font.ta_Name=NULL;
  777.                               free(CurrentNode->dn_FontDesc);
  778.                               CurrentNode->dn_FontDesc=NULL;
  779.                              }
  780.                            }
  781.  
  782.                            ActivateGadget(CurrentGadget,w,NULL);
  783.                           }
  784.                           break;
  785.     case GAD_PSCREEN_STR: ActivateAndSetGadget(GAD_NAME_STR);
  786.                           break;
  787.     case GAD_FONT_TXT:
  788.                           break;
  789.     case GAD_ACTIVATED:   /* Toggle flag */
  790.                           CurrentNode->dn_Flags^=DOPOF_ACTIVATED;
  791.  
  792.                           /* Activate old string gadget */
  793.                           ActivateGadget(CurrentGadget,w,NULL);
  794.                           break;
  795.     case GAD_CENTERED:    /* Toggle flag */
  796.                           CurrentNode->dn_Flags^=DOPOF_CENTERED;
  797.  
  798.                           /* Activate old string gadget */
  799.                           ActivateGadget(CurrentGadget,w,NULL);
  800.                           break;
  801.     case GAD_FRONTMOST:   /* Toggle flag */
  802.                           CurrentNode->dn_Flags^=DOPOF_FRONTMOST;
  803.  
  804.                           /* Activate old string gadget */
  805.                           ActivateGadget(CurrentGadget,w,NULL);
  806.                           break;
  807.     case GAD_MENU:        /* Toggle flag */
  808.                           CurrentNode->dn_Flags^=DOPOF_MENU;
  809.  
  810.                           /* Activate old string gadget */
  811.                           ActivateGadget(CurrentGadget,w,NULL);
  812.                           break;
  813.     case GAD_PATTERN:     /* Toggle flag */
  814.                           CurrentNode->dn_Flags^=DOPOF_PATTERN;
  815.  
  816.                           /* Activate old string gadget */
  817.                           ActivateGadget(CurrentGadget,w,NULL);
  818.                           break;
  819.     case GAD_POPUP:       /* Toggle flag */
  820.                           CurrentNode->dn_Flags^=DOPOF_POPUP;
  821.  
  822.                           /* Activate old string gadget */
  823.                           ActivateGadget(CurrentGadget,w,NULL);
  824.                           break;
  825.     case GAD_TEXT:        /* Toggle flag */
  826.                           CurrentNode->dn_Flags^=DOPOF_TEXT;
  827.  
  828.                           /* Activate old string gadget */
  829.                           ActivateGadget(CurrentGadget,w,NULL);
  830.                           break;
  831.     case GAD_VERTICAL:    /* Toggle flag */
  832.                           CurrentNode->dn_Flags^=DOPOF_VERTICAL;
  833.  
  834.                           /* Activate old string gadget */
  835.                           ActivateGadget(CurrentGadget,w,NULL);
  836.                           break;
  837.     case GAD_TOOLS:       if (!ReqOpen) {
  838.                            /* Save current gadget number */
  839.                            CurrentGadgetNum=GAD_TOOLS;
  840.  
  841.                            /* Open edit window */
  842.                            if (OpenDockListEditWindow(CurrentNode->dn_ToolsList,
  843.                                                       w)) {
  844.                             /* Disable window */
  845.                             DisableWindow(w);
  846.  
  847.                             /* Set update function */
  848.                             UpdateWindow=UpdateDockEditWindow;
  849.                             ReqOpen=TRUE;
  850.                            } else
  851.                             DisplayBeep(NULL);
  852.                           }
  853.                           break;
  854.     case GAD_OK: {
  855.      char *s;
  856.  
  857.      /* Free old string */
  858.      if (s=CurrentNode->dn_Node.ln_Name) free(s);
  859.      if (s=CurrentNode->dn_HotKey) free(s);
  860.      if (s=CurrentNode->dn_PubScreen) free(s);
  861.      if (s=CurrentNode->dn_Title) free(s);
  862.  
  863.      /* Duplicate new string */
  864.      if (((CurrentNode->dn_Node.ln_Name=
  865.            DuplicateBuffer(gdata[GAD_NAME_STR].gadget)) != (char *) -1) &&
  866.          ((CurrentNode->dn_HotKey=
  867.             DuplicateBuffer(gdata[GAD_HOTKEY_STR].gadget)) != (char *) -1) &&
  868.          ((CurrentNode->dn_PubScreen=
  869.             DuplicateBuffer(gdata[GAD_PSCREEN_STR].gadget)) != (char *) -1) &&
  870.          ((CurrentNode->dn_Title=
  871.             DuplicateBuffer(gdata[GAD_TITLE_STR].gadget)) != (char *) -1)) {
  872.       /* Copy integer gadget values */
  873.       CurrentNode->dn_XPos=
  874.        ((struct StringInfo *) gdata[GAD_XPOS_INT].gadget->SpecialInfo)->LongInt;
  875.       CurrentNode->dn_YPos=
  876.        ((struct StringInfo *) gdata[GAD_YPOS_INT].gadget->SpecialInfo)->LongInt;
  877.       CurrentNode->dn_Columns=
  878.        ((struct StringInfo *) gdata[GAD_COLUMNS_INT].gadget->SpecialInfo)
  879.         ->LongInt;
  880.  
  881.       NewNode=CurrentNode;
  882.      } else {
  883.       /* Couldn't copy strings */
  884.       NewNode=(struct Node *) -1;
  885.       CurrentNode->dn_Node.ln_Name=NULL;
  886.       CurrentNode->dn_HotKey=NULL;
  887.       CurrentNode->dn_PubScreen=NULL;
  888.       CurrentNode->dn_Title=NULL;
  889.       FreeDockNode((struct Node *) CurrentNode);
  890.      }
  891.     }
  892.     break;
  893.     case GAD_CANCEL:      NewNode=(struct Node *) -1;
  894.                           FreeDockNode((struct Node *) CurrentNode);
  895.                           break;
  896.    }
  897.    break;
  898.  }
  899.  
  900.  /* Close window? */
  901.  if (NewNode) {
  902.   /* Yes. But first reply message!!! */
  903.   GT_ReplyIMsg(msg);
  904.   CloseDockEditWindow();
  905.  }
  906.  
  907.  return(NewNode);
  908. }
  909.  
  910. /* Update dock edit window */
  911. void UpdateDockEditWindow(void *data)
  912. {
  913.  /* Which data? */
  914.  switch (CurrentGadgetNum) {
  915.   case GAD_PSCREEN_BUT: /* Got data? */
  916.                         if (data != LREQRET_CANCEL) {
  917.                          char *new;
  918.  
  919.                          /* Selected something? */
  920.                          new=(data == LREQRET_NOSELECT) ?
  921.                               NULL : ((struct Node *) data)->ln_Name;
  922.  
  923.                          /* set new public screen name */
  924.                          GT_SetGadgetAttrs(gdata[GAD_PSCREEN_STR].gadget,w,
  925.                                            NULL,GTST_String,new,TAG_DONE);
  926.                         }
  927.                         break;
  928.   case GAD_TOOLS:       /* Got data? */
  929.                         if (data != (void *) -1) {
  930.                          /* Free old tools list */
  931.                          if (CurrentNode->dn_ToolsList)
  932.                           FreeToolsList(CurrentNode->dn_ToolsList);
  933.  
  934.                          /* Set new tools list */
  935.                          CurrentNode->dn_ToolsList=data;
  936.                         }
  937.                         break;
  938.  }
  939.  
  940.  /* Activate old string gadget */
  941.  ActivateGadget(CurrentGadget,w,NULL);
  942.  
  943.  /* Enable window */
  944.  EnableWindow(w,WINDOW_IDCMP);
  945.  
  946.  /* Restore update function pointer */
  947.  UpdateWindow=UpdateMainWindow;
  948.  CurrentWindow=w;
  949.  ReqOpen=FALSE;
  950. }
  951.  
  952. /* Read TMDO IFF chunk into Dock node */
  953. struct Node *ReadDockNode(UBYTE *buf)
  954. {
  955.  struct DockNode *dn;
  956.  
  957.  /* Allocate memory for node */
  958.  if (dn=AllocMem(sizeof(struct DockNode),MEMF_PUBLIC|MEMF_CLEAR)) {
  959.   struct DockPrefsObject *dpo=buf;
  960.   ULONG sbits=dpo->dpo_StringBits;
  961.   UBYTE *ptr=dpo+1;
  962.   struct List *toolslist;
  963.  
  964.   if ((!(sbits & DOPO_NAME) || (dn->dn_Node.ln_Name=GetConfigStr(&ptr))) &&
  965.       (!(sbits & DOPO_HOTKEY) || (dn->dn_HotKey=GetConfigStr(&ptr))) &&
  966.       (!(sbits & DOPO_PSCREEN) || (dn->dn_PubScreen=GetConfigStr(&ptr))) &&
  967.       (!(sbits & DOPO_TITLE) || (dn->dn_Title=GetConfigStr(&ptr))) &&
  968.       (!(sbits & DOPO_FONTNAME) || (dn->dn_Font.ta_Name=GetConfigStr(&ptr))) &&
  969.       (toolslist=malloc(sizeof(struct List)))) {
  970.    LONG tools=0;
  971.    UBYTE tlflags;
  972.  
  973.    /* Init list */
  974.    NewList(toolslist);
  975.    dn->dn_ToolsList=toolslist;
  976.  
  977.    /* Get tools */
  978.    while ((tlflags=*ptr++) & DOPOT_CONTINUE) {
  979.     struct ToolNode *tn;
  980.  
  981.     if (tn=AllocMem(sizeof(struct ToolNode),MEMF_PUBLIC|MEMF_CLEAR))
  982.      if ((!(tlflags & DOPOT_EXEC) || (tn->tn_Node.ln_Name=
  983.                                        GetConfigStr(&ptr))) &&
  984.          (!(tlflags & DOPOT_IMAGE) || (tn->tn_Image=GetConfigStr(&ptr))) &&
  985.          (!(tlflags & DOPOT_SOUND) || (tn->tn_Sound=GetConfigStr(&ptr)))) {
  986.       /* Add tool to list */
  987.       AddTail(toolslist,(struct Node *) tn);
  988.  
  989.       /* All OK. */
  990.       tools++;
  991.      } else {
  992.       /* Error */
  993.       tools=-1;
  994.       break;
  995.      }
  996.     else {
  997.      /* No memory. */
  998.      tools=-1;
  999.      break;
  1000.     }
  1001.    }
  1002.  
  1003.    /* Error? */
  1004.    if (tools!=-1) {
  1005.     /* Got tools? */
  1006.     if (tools==0) {
  1007.      /* No, free list structure */
  1008.      free(toolslist);
  1009.      dn->dn_ToolsList=NULL;
  1010.     }
  1011.  
  1012.     /* Copy flags & values */
  1013.     dn->dn_Flags=dpo->dpo_Flags;
  1014.     dn->dn_XPos=dpo->dpo_XPos;
  1015.     dn->dn_YPos=dpo->dpo_YPos;
  1016.     dn->dn_Columns=dpo->dpo_Columns;
  1017.     dn->dn_Font.ta_YSize=dpo->dpo_Font.ta_YSize;
  1018.     dn->dn_Font.ta_Style=dpo->dpo_Font.ta_Style;
  1019.     dn->dn_Font.ta_Flags=dpo->dpo_Font.ta_Flags;
  1020.  
  1021.     /* All OK. */
  1022.     return(dn);
  1023.    }
  1024.   }
  1025.  
  1026.   /* Call failed */
  1027.   FreeDockNode((struct Node *) dn);
  1028.  }
  1029.  return(NULL);
  1030. }
  1031.  
  1032. /* Write Dock node to TMDO IFF chunk */
  1033. BOOL WriteDockNode(struct IFFHandle *iff, UBYTE *buf, struct Node *node)
  1034. {
  1035.  struct DockNode *dn=node;
  1036.  struct DockPrefsObject *dpo=buf;
  1037.  ULONG sbits=0;
  1038.  UBYTE *ptr=dpo+1;
  1039.  
  1040.  /* Copy strings */
  1041.  if (PutConfigStr(dn->dn_Node.ln_Name,&ptr)) sbits|=DOPO_NAME;
  1042.  if (PutConfigStr(dn->dn_HotKey,&ptr)) sbits|=DOPO_HOTKEY;
  1043.  if (PutConfigStr(dn->dn_PubScreen,&ptr)) sbits|=DOPO_PSCREEN;
  1044.  if (PutConfigStr(dn->dn_Title,&ptr)) sbits|=DOPO_TITLE;
  1045.  if (PutConfigStr(dn->dn_Font.ta_Name,&ptr)) sbits|=DOPO_FONTNAME;
  1046.  
  1047.  /* set string bits */
  1048.  dpo->dpo_StringBits=sbits;
  1049.  
  1050.  /* Write tool list */
  1051.  if (dn->dn_ToolsList) {
  1052.   struct ToolNode *tn=GetHead(dn->dn_ToolsList);
  1053.  
  1054.   while (tn) {
  1055.    UBYTE *flptr=ptr++;
  1056.    UBYTE tfl=DOPOT_CONTINUE;
  1057.  
  1058.    if (PutConfigStr(tn->tn_Node.ln_Name,&ptr)) tfl|=DOPOT_EXEC;
  1059.    if (PutConfigStr(tn->tn_Image,&ptr)) tfl|=DOPOT_IMAGE;
  1060.    if (PutConfigStr(tn->tn_Sound,&ptr)) tfl|=DOPOT_SOUND;
  1061.  
  1062.    /* Put flags */
  1063.    *flptr=tfl;
  1064.  
  1065.    /* Get next node */
  1066.    tn=GetSucc(tn);
  1067.   }
  1068.  }
  1069.  
  1070.  /* Append terminator */
  1071.  *ptr++=0;
  1072.  
  1073.  /* Copy flags & values */
  1074.  dpo->dpo_Flags=dn->dn_Flags;
  1075.  dpo->dpo_XPos=dn->dn_XPos;
  1076.  dpo->dpo_YPos=dn->dn_YPos;
  1077.  dpo->dpo_Columns=dn->dn_Columns;
  1078.  dpo->dpo_Font.ta_YSize=dn->dn_Font.ta_YSize;
  1079.  dpo->dpo_Font.ta_Style=dn->dn_Font.ta_Style;
  1080.  dpo->dpo_Font.ta_Flags=dn->dn_Font.ta_Flags;
  1081.  
  1082.  /* calculate length */
  1083.  sbits=ptr-buf;
  1084.  
  1085.  DEBUG_PRINTF("chunk size %ld\n",sbits);
  1086.  
  1087.  /* Open chunk */
  1088.  if (PushChunk(iff,0,ID_TMDO,sbits)) return(FALSE);
  1089.  
  1090.  /* Write chunk */
  1091.  if (WriteChunkBytes(iff,buf,sbits)!=sbits) return(FALSE);
  1092.  
  1093.  /* Close chunk */
  1094.  if (PopChunk(iff)) return(FALSE);
  1095.  
  1096.  /* All OK. */
  1097.  return(TRUE);
  1098. }
  1099.